package com.reus.execute;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;

/**
 * description: mapper接口代理类
 * copyright: Copyright (c) 2018-2021
 * company: iSysCore Tech. Co., Ltd.
 *
 * @author liuxq@isyscore.com
 * @version 1.0
 * @date 2021-10-19 19:18:17
 */
public class MapperProxy<T> implements InvocationHandler {

    /**
     * 要代理的mapper接口类
     */
    private Class<T> interfaces;

    /**
     * 具体的执行器，执行mapper中的一个方法相当于执行一条sql语句
     */
    private SimpleExecutor executor;

    public MapperProxy(Class<T> interfaces, SimpleExecutor executor) {
        this.interfaces = interfaces;
        this.executor = executor;
    }

    /**
     * 反射方法，该方法自定义需要代理的逻辑。不了解可以去看下JAVA动态代理技术
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        /**object方法直接代理*/
        if (Object.class.equals(method.getDeclaringClass())) {
            result = method.invoke(this, args);
        } else {
            // 获取方法是select还是非select方法
            Integer methodType = executor.mapperCore.getMethodType(method);

            if (methodType == null) {
                throw new RuntimeException("method is normal sql method");
            }
            if (methodType == 1) {
                /**调用执行器的select方法，返回集合类*/
                List<Object> list = executor.select(method, args);
                result = list;
                /**查看接口的返回是List，还是单个对象*/
                if (!executor.mapperCore.getHasSet(method)) {
                    if (list.size() == 0) {
                        result = null;
                    } else {
                        /**单个对象就直接取第一个*/
                        result = list.get(0);
                    }
                }

            } else {
                /**返回受影响的行数*/
                Integer count = executor.update(method, args);
                result = count;
            }
        }
        return result;
    }

    /**
     * 构建代理类
     */
    public T initialization() {
        return (T) Proxy.newProxyInstance(interfaces.getClassLoader(), new Class[]{interfaces}, this);
    }
}
